from networkFramework import *
from dataStruct import quoteStruct as qStruct
from dataStruct import orderStruct as oStruct
from dataStruct import snapshotStruct as sStruct
from framework import *
from operator import itemgetter, attrgetter
import select
import sys
import time


class engine():
    def __init__(self):
        self.configDataME = getMEConfig()
        self.snapshotConfig = getSSConfig()
        self.quoteConfig = getQSConfig()
        self.oRecvConfig = getOSConfig()
        self.bidsObjs = []
        self.offersObjs = []
        self.fullBook = initFullBook()
        self.timeout = 10
        self.timer = time.time() + self.timeout
        self.orderNumber = 2000
        self.quoteServer()
        self.snapshotServer()
        self.orderRecServer()
        self.orderRecever()

             
    def quoteServer(self):
        self.quoteObj = qStruct()
        self.quoteSendConn = senderUDPConn(self.quoteConfig['host'],self.quoteConfig['port'])

        
    def snapshotServer(self):
        self.snapObj = sStruct()
        self.snapShotConn = senderUDPConn(self.snapshotConfig['host'],self.snapshotConfig['port'])
        

    def orderRecServer(self):
        self.orderRecvObj = oStruct()
        bufferSize = self.orderRecvObj.getBuffSize()
        self.oRecSock = reciverUDPConn(self.oRecvConfig['host'], self.oRecvConfig['port'], bufferSize)
        
              
    def orderRecever(self):
        dataList = []
        wList = []
        eList = []
        dataList.append(self.oRecSock.rUDPSock)
        
        while True:
            if time.time() > self.timer:
                #self.sendSnapshot()
                self.timer = time.time() + self.timeout
                
            inputReady, write, error = select.select(dataList, wList, eList, 2)
            

            if self.oRecSock.rUDPSock in inputReady:
                self.orderRecvObj.buffer = self.oRecSock.recData()
                order = self.orderRecvObj.getValues()
                print order
                self.orderToOrderObj(order)
                
    
    def orderToOrderObj(self, order):
        
        orderNum = str(order[0]) + '-' + str(self.orderNumber)
        orderObj = orderObject(order[1],     \
                               order[0],     \
                               orderNum,     \
                               order[2],     \
                               order[4],     \
                               order[3],     \
                               time.time()   \
                               )
        
        self.orderNumber += 1
        self.checkBook(orderObj)
        
        
    def checkBook(self, orderObj):
        
        if orderObj.side == 0:
            if len(self.offersObjs) == 0 and len(self.bidsObjs) == 0:
                self.insertBid(orderObj)
            
            elif len (self.offersObjs) > 0 and len(self.bidsObjs) == 0:
                if orderObj.price < self.offersObjs[0].price:
                    self.insertBid(orderObj)
                else:
                    self.tradeIntoOffer(orderObj)
                    
            elif len (self.offersObjs) > 0 and len(self.bidsObjs) > 0:
                if orderObj.price < self.offersObjs[0].price:
                    self.insertBid(orderObj)
                else:
                    self.tradeIntoOffer(orderObj) 
            
            else:
                self.insertBid(orderObj)    


        else:
            if len(self.offersObjs) == 0 and len(self.bidsObjs) == 0:
                self.insertOffer(orderObj)
            
            elif len (self.bidsObjs) > 0 and len(self.offersObjs) == 0:
                if orderObj.price > self.bidsObjs[0].price:
                    self.insertOffer(orderObj)
                else:
                    self.tradeIntoBid(orderObj)
                    
            elif len (self.bidsObjs) > 0 and len(self.offersObjs) > 0:
                if orderObj.price > self.bidsObjs[0].price:
                    self.insertOffer(orderObj)
                else:
                    self.tradeIntoBid(orderObj) 
            
            else:
                self.insertOffer(orderObj)
             
                
    def tradeIntoBid(self, orderObj):
        
        while orderObj.size >= 0:
            
            if len(self.bidsObjs) == 0:
                self.insertOffer(orderObj)
                return
            try:
                bid = self.bidsObjs.pop(0)
            except:
                return
            
            if orderObj.size > bid.size:
                orderObj.size -= bid.size
                print "Trade offer into \nBid: ", bid, '\nOffer', orderObj
                self.sendQuote(bid)
                
            else:
                bid.size -= orderObj.size
                print "Trade offer into \nBid: ", bid, '\nOffer', orderObj
                self.sendQuote(orderObj)
                if bid.size == 0:
                    return
            
    
    
    def tradeIntoOffer(self, orderObj):
        
        while orderObj.size > 0:
            
            if len(self.offersObjs) == 0:
                self.insertBid(orderObj)
                return
            try:
                offer = self.offersObjs.pop(0)
            except:
                return
            
            if orderObj.size > offer.size:
                orderObj.size -= offer.size
                print "Trade offer into \nOffer: ", offer, '\nOffer', orderObj
                self.sendQuote(offer)
                
            else:
                offer.size -= orderObj.size
                print "Trade offer into \nOffer: ", offer, '\nOffer', orderObj
                self.sendQuote(orderObj)
                if offer.size == 0:
                    return
    
    
    def insertBid(self, orderObj):
        self.bidsObjs.append(orderObj)
        self.bidsObjs = sorted(self.bidsObjs, key = attrgetter('price', 'time'), reverse = True)
        self.sendQuote(orderObj)
        
    def insertOffer(self, orderObj):
        self.offersObjs.append(orderObj)
        self.offersObjs = sorted(self.offersObjs, key = attrgetter('price', 'time'))
        self.sendQuote(orderObj)
        
    
    def sendQuote(self, qObj):
        quoteList = [qObj.symbol, qObj.side, qObj.size, qObj.price]
        print "quote: ", quoteList
        self.quoteObj.bufferValues(quoteList)
        self.quoteSendConn.sendData(self.quoteObj.buffer.raw)
        
        self.sendSnapshot()
    
    
    def sendSnapshot(self):
        bookList = self.getFullBook()
        
        self.snapObj.bufferValues(bookList)
        self.snapShotConn.sendData(self.snapObj.buffer.raw)
        
        printBook(bookList)
        
    
    def getFullBook(self):
        bookDict = {}
        index = 1
        bCount = 0
        oCount = 0
        bids = self.getTopFivePrices('bid')
        offers = self.getTopFivePrices('offer')

        while index <= 5:

            try:
                bid = bids.pop(0)
                bQuant = bid.size
                bPrice = bid.price
            except:
                bQuant = 0
                bPrice = 0.0                    

            try:
                offer = offers.pop(0)
                oQuant = offer.size
                oPrice = offer.price
            except:
                oQuant = 0
                oPrice = 0.0         

            bookDict['bSize' + str(index)] = bQuant
            bookDict['bid' + str(index)] = bPrice
            bookDict['aSize' + str(index)] = oQuant
            bookDict['ask' + str(index)] = oPrice
            
            index += 1
            
        return bookDictToList(bookDict)
            
                    
    def getTopFivePrices(self, bidOffer):
        priceList = []
        count = 0
        index = 0
        
        if bidOffer == 'bid':
            tempBook = self.bidsObjs[:]
            side = 0
        else:
            tempBook = self.offersObjs[:]
            side = 1
            
        if len(tempBook) == 0:
            return priceList
        
        order = tempBook.pop(0)

        currentVol = 0
        currentPrice = order.price
        
        quoteObj = quoteObject(order.symbol, order.price)
        
        while count < 20:
            
            if quoteObj.price == order.price:
                quoteObj.size += order.size
            
            else:
                priceList.append(quoteObj)
                quoteObj = quoteObject(order.symbol, order.price, order.size)
                count += 1
                
            try:
                order = tempBook.pop(0)
            
            except:
                priceList.append(quoteObj)
                return priceList       
            

        return priceList
            

            
def main():
    Exchange = engine()
    
    
if __name__ == "__main__":
    main()

